package cn.schoolwow.ams.test.module.testcase.flow.button;

import cn.schoolwow.ams.domain.block.common.operation.CustomerMessage;
import cn.schoolwow.ams.module.block.listBlock.common.domain.operation.ListBlockRequest;
import cn.schoolwow.ams.test.entity.TestCase;
import cn.schoolwow.ams.test.module.testcase.domain.TestCaseFlow;
import cn.schoolwow.quickdao.domain.DAO;
import cn.schoolwow.quickdao.domain.database.dml.UpdateType;
import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.dto.FlowContextDataRange;
import cn.schoolwow.quickflow.exception.QuickFlowRuntimeException;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class ExecuteTestCaseFlow implements BusinessFlow {
    @Autowired
    private DAO starterDAO;

    @Autowired
    private QuickFlow testcaseFlow;

    @Autowired(required = false)
    private List<TestCaseFlow> testCaseFlowList;

    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        if(null==testCaseFlowList||testCaseFlowList.isEmpty()){
            throw new IllegalArgumentException("当前未扫描到测试用例流程");
        }
        setTestCaseList(flowContext);
        executeTestCase(flowContext);
    }

    @Override
    public String name() {
        return "执行测试用例流程";
    }

    private void setTestCaseList(FlowContext flowContext){
        ListBlockRequest listBlockRequest = flowContext.checkInstanceData(ListBlockRequest.class);

        List<TestCase> testCaseList = new ArrayList<>();
        if("执行全部测试用例".equalsIgnoreCase(listBlockRequest.label)){
            testCaseList.addAll(starterDAO.query(TestCase.class)
                    .execute()
                    .getList());
        }else if("执行分类流程".equalsIgnoreCase(listBlockRequest.label)){
            String categoryName = listBlockRequest.search.getString("categoryName");
            Validate.notEmpty(categoryName, "请选择分类名称");
            testCaseList.addAll(starterDAO.query(TestCase.class)
                    .addQuery("categoryName", categoryName)
                    .execute()
                    .getList());
        }else{
            if(null!=listBlockRequest.array){
                testCaseList.addAll(listBlockRequest.array.toJavaList(TestCase.class));
            }else{
                testCaseList.add(listBlockRequest.row.toJavaObject(TestCase.class));
            }
        }

        flowContext.putCurrentFlowData("testCaseList", testCaseList);
    }

    private void executeTestCase(FlowContext flowContext){
        List<TestCase> testCaseList = (List<TestCase>) flowContext.checkData("testCaseList");

        int successCount = 0, failCount = 0;
        for(TestCase testCase:testCaseList) {
            for (TestCaseFlow testCaseFlow : testCaseFlowList) {
                if (!(testCaseFlow instanceof BusinessFlow)) {
                    throw new IllegalArgumentException("测试用例流程必须为BusinessFlow类型!当前测试流程类:" + testCaseFlow.getClass().getName());
                }
                BusinessFlow businessFlow = (BusinessFlow) testCaseFlow;
                if (!testCase.getName().equalsIgnoreCase(businessFlow.name())) {
                    continue;
                }
                flowContext.putCurrentFlowInstanceData(businessFlow, BusinessFlow.class);
                flowContext.putCurrentFlowInstanceData(testCase);
                executeSingleTestCase(flowContext);
                if(flowContext.containKey("hasException")){
                    failCount++;
                }else{
                    successCount++;
                }
                flowContext.removeData("hasException");
            }
        }

        CustomerMessage customerMessage = null;
        if(successCount==0){
            customerMessage = new CustomerMessage("danger","测试用例执行失败");
        }else if(failCount==0){
            customerMessage = new CustomerMessage("测试用例执行成功");
        }else{
            customerMessage = new CustomerMessage("danger", "测试用例执行成功"+successCount+"个,执行失败:"+failCount+"个");
        }
        flowContext.putTemporaryInstanceData(customerMessage);
    }

    private void executeSingleTestCase(FlowContext flowContext) {
        BusinessFlow testCaseFlow = flowContext.checkInstanceData(BusinessFlow.class);
        TestCase testCase = flowContext.checkInstanceData(TestCase.class);

        System.out.println("执行测试用例["+testCase.getName()+"]");
        try {
            testcaseFlow.startFlow(testCaseFlow)
                    .putData("testcaseId", testCase.getId())
                    .execute();

            testCase.setPass(true);
            testCase.setException(null);
        }catch (Exception e){
            if(e instanceof QuickFlowRuntimeException){
                QuickFlowRuntimeException ex = (QuickFlowRuntimeException) e;
                e = ex.targetException;
            }
            testCase.setPass(false);
            testCase.setException(e.getMessage());
            e.printStackTrace();
            flowContext.putData("hasException", true);
        }finally {
            starterDAO.updateType(UpdateType.UpdateById).update(testCase);
        }
    }

}
